﻿using System;
using System.Runtime.InteropServices;

namespace WinAPI32Library
{
    public static class Kernel32
    {
        /// <summary>
        /// Infinite wait. CreateThread method.
        /// </summary>
        public const uint INFINITE = 0xFFFFFFFF;
        /// <summary>
        /// Delegate for CreateThread method.
        /// </summary>
        /// <param name="lpParam">Method to be executed withing thread.</param>
        /// <returns>Google it.</returns>
        public delegate uint LPTHREAD_START_ROUTINE(uint lpParam);

        /// <summary>
        /// Creation flags.
        /// </summary>
        public enum CreationFlags : uint
        {
            CREATE_NEW_CONSOLE = 0x00000010,
            CREATE_SUSPENDED = 0x00000004,
            CREATE_PROTECTED_PROCESS = 0x00040000,
            CREATE_NO_WINDOW = 0x08000000
        }

        /// <summary>
        /// Get elapsed time from structure.
        /// </summary>
        /// <param name="start">Start time.</param>
        /// <param name="stop">Stop time.</param>
        /// <returns>Time elapsed.</returns>
        public static TimeSpan Elapsed(long start, long stop)
        {
            if (stop == 0) return new TimeSpan(0);
            long elapsed = stop - start;
            TimeSpan result = TimeSpan.FromMilliseconds(elapsed / 10000);
            return result;
        }

        /// <summary>
        /// Thread access parameter in OpenProcess.
        /// </summary>
        public enum ThreadAccess : int
        {
            TERMINATE = (0x0001),
            SUSPEND_RESUME = (0x0002),
            GET_CONTEXT = (0x0008),
            SET_CONTEXT = (0x0010),
            SET_INFORMATION = (0x0020),
            QUERY_INFORMATION = (0x0040),
            SET_THREAD_TOKEN = (0x0080),
            IMPERSONATE = (0x0100),
            DIRECT_IMPERSONATION = (0x0200)
        }

        /// <summary>
        /// Thread priority for SetThreadPriority.
        /// </summary>
        public enum ThreadPriority : int
        {
            THREAD_PRIORITY_ABOVE_NORMAL = 1,
            THREAD_PRIORITY_BELOW_NORMAL = -1,
            THREAD_PRIORITY_HIGHEST = 2,
            THREAD_PRIORITY_IDLE = -15,
            THREAD_PRIORITY_LOWEST = -2,
            THREAD_PRIORITY_NORMAL = 0,
            THREAD_PRIORITY_TIME_CRITICAL = 15
        }

        /// <summary>
        /// Process priority class for SetPriority class.
        /// </summary>
        public enum ProcessPriorityClass : uint
        {
            ABOVE_NORMAL_PRIORITY_CLASS = 0x00008000,
            BELOW_NORMAL_PRIORITY_CLASS = 0x00004000,
            HIGH_PRIORITY_CLASS = 0x00000080,
            IDLE_PRIORITY_CLASS = 0x00000040,
            NORMAL_PRIORITY_CLASS = 0x00000020,
            REALTIME_PRIORITY_CLASS = 0x00000100
        }

        /// <summary>
        /// Desired access in mutexes, events, semaphores, timers.
        /// </summary>
        public enum SyncObjectAccess : uint
        {
            DELETE = 0x00010000,
            READ_CONTROL = 0x00020000,
            WRITE_DAC = 0x00040000,
            WRITE_OWNER = 0x00080000,
            SYNCHRONIZE = 0x00100000,
            EVENT_ALL_ACCESS = 0x001F0003,
            EVENT_MODIFY_STATE = 0x00000002,
            MUTEX_ALL_ACCESS = 0x001F0001,
            MUTEX_MODIFY_STATE = 0x00000001,
            SEMAPHORE_ALL_ACCESS = 0x001F0003,
            SEMAPHORE_MODIFY_STATE = 0x00000002,
            TIMER_ALL_ACCESS = 0x001F0003,
            TIMER_MODIFY_STATE = 0x00000002,
            TIMER_QUERY_STATE = 0x00000001
        }

        /// <summary>
        /// Information about process. Is used by CreateProcess function.
        /// </summary>
        public struct PROCESS_INFORMATION
        {
            public IntPtr hProcess;
            public IntPtr hThread;
            public uint dwProcessId;
            public uint dwThreadId;
        }

        /// <summary>
        /// Startup information. Is used by CreateProcess function.
        /// </summary>
        public struct STARTUP_INFO
        {
            public uint cb;
            public string lpReserved;
            public string lpDesktop;
            public string lpTitle;
            public uint dwX;
            public uint dwY;
            public uint dwXSize;
            public uint dwYSize;
            public uint dwXCountChars;
            public uint dwYCountChars;
            public uint dwFillAttribute;
            public uint dwFlags;
            public short wShowWindow;
            public short cbReserved2;
            public IntPtr lpReserved2;
            public IntPtr hStdInput;
            public IntPtr hStdOutput;
            public IntPtr hStdError;
        }

        /// <summary>
        /// Represents security attributes structure for multiply methods.
        /// </summary>
        public struct SECURITY_ATTRIBUTES
        {
            public int length;
            public IntPtr lpSecurityDescriptor;
            public bool bInheritHandle;
        }

        /// <summary>
        /// Dyplicate options used in DuplicateHandle method.
        /// </summary>
        public enum DuplicateOptions : uint
        {
            // Closes the source handle. This occurs regardless of any error status returned.
            DUPLICATE_CLOSE_SOURCE = (0x00000001),
            //Ignores the dwDesiredAccess parameter. The duplicate handle has the same access as the source handle.
            DUPLICATE_SAME_ACCESS = (0x00000002),
        }


        [DllImport("kernel32.dll")]
        public static extern IntPtr GetCurrentThread();

        [DllImport("kernel32.dll")]
        public static extern IntPtr GetCurrentProcess();

        [DllImport("Kernel32.dll")]
        public static extern IntPtr CreateThread(
            uint lpThreadAttributes,
            uint dwStackSize,
            LPTHREAD_START_ROUTINE lpStartAddress,
            uint lpParameter,
            uint dwCreationFlags,
            out uint lpThreadId);

        [DllImport("Kernel32.dll")]
        public static extern int CloseHandle(
            IntPtr hObject);

        [DllImport("Kernel32.dll")]
        public static extern uint WaitForSingleObject(
            IntPtr hHandle,
            uint dwMilliseconds);

        [DllImport("Kernel32.dll")]
        public static extern void Sleep(
            uint dwMilliseconds);

        [DllImport("Kernel32.dll")]
        public static extern void ResumeThread(
            IntPtr dwThread);

        [DllImport("kernel32.dll")]
        public static extern bool GetThreadTimes(
            IntPtr handle,
            out long creation,
            out long exit,
            out long kernel,
            out long user);

        [DllImport("kernel32.dll")]
        public static extern IntPtr OpenThread(
            ThreadAccess dwDesiredAccess,
            bool bInheritHandle,
            uint dwThreadId);

        [DllImport("kernel32.dll")]
        public static extern bool CreateProcess(
            string lpApplicationName,
            string lpCommandLine,
            IntPtr lpProcessAttributes,
            IntPtr lpThreadAttributes,
            bool bInheritHandles,
            uint dwCreationFlags,
            IntPtr lpEnvironment,
            string lpCurrentDirectory,
            ref STARTUP_INFO lpStartupInfo,
            out PROCESS_INFORMATION lpProcessInformation);

        [DllImport("kernel32.dll")]
        public static extern bool GetProcessTimes(
            IntPtr handle,
            out long creation,
            out long exit,
            out long kernel,
            out long user);

        [DllImport("user32.dll")]
        public static extern int MessageBox(
            IntPtr hWnd,
            String text,
            String caption,
            uint type);

        [DllImport("kernel32.dll")]
        public static extern bool GetExitCodeProcess(
            IntPtr hProcess,
            out uint lpExitCode);

        [DllImport("kernel32.dll")]
        public static extern bool SetThreadPriority(
            IntPtr hThread,
            int nPriority);

        [DllImport("kernel32.dll")]
        public static extern bool SetPriorityClass(
            IntPtr handle,
            uint priorityClass);

        [DllImport("kernel32.dll")]
        public static extern uint GetPriorityClass(
            IntPtr hProcess);

        [DllImport("kernel32.dll")]
        public static extern int GetThreadPriority(
            IntPtr hThread);

        [DllImport("kernel32.dll")]
        public static extern IntPtr CreateEvent(
            IntPtr lpEventAttributes,
            bool bManualReset,
            bool bInitialState,
            string lpName);

        [DllImport("kernel32.dll")]
        public static extern bool SetEvent(
            IntPtr hEvent);

        [DllImport("kernel32.dll")]
        public static extern bool ResetEvent(
            IntPtr hEvent);

        [DllImport("kernel32.dll")]
        public static extern uint WaitForMultipleObjects(
            uint nCount,
            IntPtr[] lpHandles,
            bool bWaitAll,
            uint dwMilliseconds);

        [DllImport("Kernel32.dll")]
        public static extern IntPtr OpenEvent(
            uint dwDesiredAccess,
            bool bInheritHandle,
            string lpName);

        [DllImport("kernel32.dll")]
        public static extern IntPtr CreateSemaphore(
             IntPtr lpSemaphoreAttributes,
             int lInitialCount,
             int lMaximumCount,
             string lpName);

        [DllImport("kernel32.dll")]
        public static extern IntPtr OpenSemaphore(
            uint dwDesiredAccess,
            bool bInheritHandle,
            string lpName);

        [DllImport("kernel32.dll")]
        public static extern bool ReleaseSemaphore(
            IntPtr hSemaphore,
            int lReleaseCount,
            IntPtr lpPreviousCount);

        [DllImport("kernel32.dll")]
        public static extern IntPtr CreateMutex(
            IntPtr lpMutexAttributes,
            bool bInitialOwner,
            string lpName);

        [DllImport("kernel32.dll")]
        public static extern IntPtr OpenMutex(
            uint dwDesiredAccess,
            bool bInheritHandle,
            string lpName);

        [DllImport("kernel32.dll")]
        public static extern bool ReleaseMutex(
            IntPtr hMutex);

        [DllImport("kernel32.dll")]
        public static extern bool CreatePipe(
            out IntPtr hReadPipe,
            out IntPtr hWritePipe,
            ref SECURITY_ATTRIBUTES lpPipeAttributes,
            uint nSize);

        [DllImport("kernel32.dll")]
        public static extern bool WriteFile(
            IntPtr hFile,
            byte[] lpBuffer,
            uint nNumberOfBytesToWrite,
            out uint lpNumberOfBytesWritten,
            ref System.Threading.NativeOverlapped lpOverlapped);

        [DllImport("kernel32.dll", SetLastError = true)]
        public static extern bool ReadFile(
            IntPtr hFile,
            byte[] lpBuffer,
            uint nNumberOfBytesToRead,
            out uint lpNumberOfBytesRead,
            ref System.Threading.NativeOverlapped lpOverlapped);

        [DllImport("kernel32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool DuplicateHandle(
            IntPtr hSourceProcessHandle,
            IntPtr hSourceHandle,
            IntPtr hTargetProcessHandle,
            out IntPtr lpTargetHandle,
            uint dwDesiredAccess,
            [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle,
            uint dwOptions);

        [DllImport("Kernel32.dll", EntryPoint = "RtlZeroMemory", SetLastError = false)]
        public static extern void ZeroMemory(
            IntPtr dest,
            IntPtr size);
    }
}
